﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using PluginInterface;

namespace JavaPlugin
{
    public class JavaPlugin : IPlugin
    {
        string output = "";
        string cssPath = "";
        string CommentRegexp = @"/\*(.|\n|\r)*?\*/|//.*?(?=\r|\n)";                               
        string JavaDoc = @"/\*\*(.|\n|\r)*?\*/";        
        List<TextType> textBlockList = new List<TextType>();

        public string Name
        {
            get { return "Java Plugin"; }
        }

        public string languageName
        {
            get { return "Java"; }
        }

        public string Extension
        {
            get { return "java"; }
        }

        public string CSSPath
        {
            get
            {
                return cssPath;
            }
            set
            {
                this.cssPath = value;
            }
        }

        public bool Injection
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

       
        private void Analizing(string inputStr)
        {
            Regex word = new Regex(@"\b[a-z]([a-z]){1,}\b");
            //Regex str = new Regex("(\".*?\")|(@\".*?\")|(\"\")|(\".*?[^\\\\]\")");            
            Regex str = new Regex("(\".*?\")|(@\".*?\")|(@\"(.|\r|\n)*?\")|(\"\")|(\".*?[^\\\\]\")");            
            Regex jdoc = new Regex(JavaDoc);
            Regex com = new Regex(CommentRegexp);
            Match fr;

            int size = inputStr.Length;
            int index = 0;

            fr = jdoc.Match(inputStr, index);
            while (fr.Success)
            {
                index = fr.Index;
                textBlockList.Add(new TextType(index, (index + fr.Value.Length), 1));
                index += fr.Value.Length;
                fr = fr.NextMatch();
            }

            fr = null;
            index = 0;                      

            fr = com.Match(inputStr, index);
            while (fr.Success)
            {                
                index = fr.Index;
                textBlockList.Add(new TextType(index, (index + fr.Value.Length), 4));
                index += fr.Value.Length; 
                fr = fr.NextMatch();
            }

            fr = null;
            index = 0;

            fr = str.Match(inputStr, index);
            while (fr.Success)
            {
                index = fr.Index;
                textBlockList.Add(new TextType(index, (index + fr.Value.Length), 3));
                index += fr.Value.Length;
                fr = fr.NextMatch();
            }

            for (index = 0; index < size; index++)
            {
                if ((inputStr[index] != ' ') && (inputStr[index] != '\n') && (inputStr[index] != ':') &&
                    (inputStr[index] != ';') && (inputStr[index] != '.') && (inputStr[index] != ',') &&
                    (inputStr[index] != '\r'))
                {
                    fr = word.Match(inputStr, index);
                    if (fr.Success)
                    {
                        if (KeyWord.isKeyWord(fr.Value))
                        {
                            index = fr.Index;
                            textBlockList.Add(new TextType(index, (index + fr.Value.Length), 2));
                            index += fr.Value.Length;
                        }
                    }
                }
            }
            

            /*for (int index = 0; index < size; index++)
            {
                if (inputStr[index] == ' ')
                    continue;
                #region Поиск коментариев
                if (inputStr[index] == '/')
                {
                    if ((index + 1) < size)
                    {
                        if (inputStr[index + 1] == '/')
                        {
                            start = index;
                            while ((inputStr[index] != '\n') && (index != size))
                            {
                                index++;
                            }
                            end = index;
                            textBlockList.Add(new TextType(start, end, 4));
                            start = -1;
                            end = -1;
                        }

                        if (inputStr[index + 1] == '*')
                        {
                            start = index;
                            index += 2;
                            while (index + 1 < size)
                            {
                                if ((inputStr[index] == '*') && (inputStr[index + 1] == '/'))
                                {
                                    index++;
                                    break;
                                }
                                else
                                    index++;
                            }
                            ++index;
                            end = index;
                            textBlockList.Add(new TextType(start, end, 4));
                            start = -1;
                            start = -1;
                        }
                    }
                }
                #endregion

                #region Поиск строк
                if ((inputStr[index] == '@') || (inputStr[index] == '"'))
                {
                    if (index + 1 < inputStr.Length)
                    {
                        if ((inputStr[index] == '"') && (inputStr[index + 1] == '"'))
                        {
                            textBlockList.Add(new TextType(index, (index + 1), 3));
                            index++;
                        }
                        else
                        {
                            fr = str.Match(inputStr, index);
                            if (fr.Success)
                            {
                                index = fr.Index;
                                textBlockList.Add(new TextType(index, (index + fr.Value.Length), 3));
                                index += fr.Value.Length;
                            }
                        }
                    }
                }
                #endregion

                #region Поиск ключевых слов и директив предкомпилятора
                if ((inputStr[index] != ' ') && (inputStr[index] != '\n') && (inputStr[index] != ':') &&
                    (inputStr[index] != ';') && (inputStr[index] != '.') && (inputStr[index] != ',') &&
                    (inputStr[index] != '\r'))
                {
                    fr = word.Match(inputStr, index);
                    if (fr.Success)
                    {
                        if (KeyWord.isKeyWord(fr.Value))
                        {
                            index = fr.Index;
                            textBlockList.Add(new TextType(index, (index + fr.Value.Length), 2));
                            index += fr.Value.Length;
                        }
                    }
                }
                #endregion

                
            }*/

        }

        private string TypeToTag(TextType block, string inputStr)
        {
            string st = "";
            string end = "</span>";

            switch (block.Type)
            {
                case 1: st = "<span class=\"dirc\">";
                    break;
                case 2: st = "<span class=\"keyw\">";
                    break;
                case 3: st = "<span class=\"str\">";
                    break;
                case 4: st = "<span class=\"comt\">";
                    break;
            }
            return string.Concat(st, inputStr.Substring(block.StartPosition, block.EndPosition - block.StartPosition), end);
        }

        private void CreateHtmlString(string inputStr)
        {
            int size = textBlockList.Count - 1;

            textBlockList.Sort(delegate(TextType t1, TextType t2)
            { return t1.StartPosition.CompareTo(t2.StartPosition); });

            if (textBlockList.Count == 0)
            {
                this.output += inputStr;
                return;
            }

            if (textBlockList[0].StartPosition == 0)
            {
                this.output += TypeToTag(textBlockList[0], inputStr);
            }
            else
            {
                this.output += string.Concat(inputStr.Substring(0, textBlockList[0].StartPosition),
                    TypeToTag(textBlockList[0], inputStr));
            }
            int b0, b1, b2;
            for (int i = 1; i <= size; i++)
            {
                b0 = textBlockList[i - 1].StartPosition;
                b1 = textBlockList[i - 1].EndPosition;
                b2 = textBlockList[i].StartPosition;
                if ((b2 - b1) > 0)//&& (b0 < b1)
                {
                    this.output += inputStr.Substring(b1, b2 - b1);
                    this.output += TypeToTag(textBlockList[i], inputStr);
                }
                else
                {
                    textBlockList[i].EndPosition = b1;
                }
            }
            if (textBlockList[size].EndPosition < (inputStr.Length - 1))
            {
                this.output += inputStr.Substring(textBlockList[size].EndPosition);
            }

        }

        public string SourcetoHtml(string input)
        {
            output = "";
            textBlockList.Clear();
            
            output += "<HTML>  ";
            output += "<HEAD>  ";

            if (this.CSSPath != "")
            {
                output += "link rel=\"stylesheet\" type=\"text/css\" href=\"" + this.CSSPath + ".css\"> \n";
            }
            else
            {
                output += DefaultCSS.sheet;
            }
            output += "<pre>";
            Analizing(input);
            CreateHtmlString(input);
            output += "</pre>";
            output += "</HEAD>  ";
            output += "</HTML>  ";
            return output;
        }
    }
}
